package com.gxy.learn.backup.shiroauth.shiro.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.gxy.learn.backup.shiroauth.shiro.config.JwtConstant;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;

/**
 * Description(这里用一句话描述这个方法的作用)
 * author: Gao xueyong
 * Create at: 2022/1/4 下午10:54
 */
@Slf4j
public class JwtUtil {
    /**
     * 生成加密token
     *
     * @param username 用户名
     * @return 加密的token
     */
    public static String sign(String username,Integer tokenVersion) {
        Date date = new Date(System.currentTimeMillis() + JwtConstant.TOKEN_EXPIRE_TIME);
        Algorithm algorithm = Algorithm.HMAC256(secret());
        // 附带username信息
        return JWT.create()
                .withClaim(JwtConstant.USER_NAME, username)
                .withClaim(loginVersionKey(username), null == tokenVersion? JwtConstant.CLAIM_KEY_LOGIN_VERSION_VAL:tokenVersion)
                .withExpiresAt(date)
                .withIssuedAt(new Date())
                .sign(algorithm);
    }

    /**
     * 校验token是否正确
     *
     * @param token 秘钥
     * @return 是否正确
     */
    public static boolean verify(String token) {
        try {
            // 根据密码生成JWT效验器
            Algorithm algorithm = Algorithm.HMAC256(secret());
            JWTVerifier verifier = JWT.require(algorithm).withClaim(JwtConstant.USER_NAME, getUsername(token)).build();
            // 效验TOKEN
            DecodedJWT jwt = verifier.verify(token);
            log.info(jwt + ":-token is valid");
            return true;
        } catch (Exception e) {
            log.info("The token is invalid{}", e.getMessage());
            return false;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(JwtConstant.USER_NAME).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的签发时间
     */
    public static Date getIssuedAt(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getIssuedAt();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * token是否过期
     *
     * @return true：过期
     */
    public static boolean isTokenExpired(String token) {
        Date now = Calendar.getInstance().getTime();
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getExpiresAt().before(now);
    }

    /**
     * 获取登录版本号
     * @param token
     * @return
     */
    public static Integer getLoginVersion(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(loginVersionKey(getUsername(token))).asInt();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
    /**
     * 获取秘钥
     *
     * @return
     */
    public static String secret() {
        InputStream inputStream = JwtUtil.class.getClassLoader().getResourceAsStream("application.properties");
        try {
            Properties properties = new Properties();
            properties.load(inputStream);
            return properties.getProperty("com.gxy.jwt.secret");
        } catch (IOException e) {
            log.error("读取配置失败！");
            return null;
        }
    }
    /**
     * 获取登录版本号
     *
     * @param userName
     * @return
     */
    public static String loginVersionKey(String userName) {
        return String.format("%s-%s", userName, JwtConstant.CLAIM_KEY_LOGIN_VERSION);
    }


}